package ui;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Vector;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;

import model.BlogPost;
import model.Sentence;
import model.Topic;

public class MainPanel extends JFrame {
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	private JTextArea annotator;
	private JComboBox topicNum;
	private JButton openButton = new JButton("Load");
	private JButton labelButton = new JButton("Label");
	private JButton saveButton = new JButton("Save To Disk");
	private JButton saveToDB = new JButton("Upload to DB");
	JTextArea display;
	JFileChooser fc = new JFileChooser();
	LabelingUI labelingUI = new LabelingUI();
	Connection conn = null;
	private final String DB_URL = "jdbc:mysql://azhou.db.8652200.hostedresource.com/azhou";
	private final String USRNAME = "azhou";
	private final String PASSWD = "Apassw0rds";
	final String lineDividerStars = "\n**************************************************\n";
	final String lineDividerDashes = "\n--------------------------------------------------\n";

	public void init() {
		startUI();
		setSize(800, 600);
		setVisible(true);
		startDBConnection();
	}

	private void startDBConnection() {
		try {
			Class.forName("com.mysql.jdbc.Driver").newInstance();
			display.append("Attempting to connect to the database ... \n");
			conn = DriverManager.getConnection(DB_URL, USRNAME, PASSWD);
			display.append("Database connection established.\n");

			// Preload the topic list
			Statement getTopicsStatement;
			getTopicsStatement = conn.createStatement();
			getTopicsStatement
					.executeQuery("SELECT distinct topic_no FROM post");
			ResultSet returnedTopics = getTopicsStatement.getResultSet();
			while (returnedTopics.next()) {
				topicNum.addItem(returnedTopics.getString("topic_no"));
			}
		} catch (InstantiationException e) {
			display.append(e.getMessage());
		} catch (IllegalAccessException e) {
			display.append(e.getMessage());
		} catch (ClassNotFoundException e) {
			display.append(e.getMessage());
		} catch (SQLException e) {
			display.append(e.getMessage());
		}
	}

	public void startUI() {
		annotator = new JTextArea();
		annotator.setPreferredSize(new Dimension(100, 20));
		topicNum = new JComboBox();
		display = new JTextArea(5, 80);
		display.setMargin(new Insets(5, 5, 5, 5));
		display.setEditable(false);
		display.setLineWrap(true);
		JScrollPane logScrollPane = new JScrollPane(display);

		JPanel buttonPanel = new JPanel(); // use FlowLayout
		buttonPanel.add(new JLabel("Annotator: "));
		buttonPanel.add(annotator);
		buttonPanel.add(new JLabel("   Topic: "));
		buttonPanel.add(topicNum);
		buttonPanel.add(openButton);
		buttonPanel.add(labelButton);
		buttonPanel.add(saveButton);
		buttonPanel.add(saveToDB);

		// mainContainer.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setTitle("Sentence Labeling System - Main Panel");
		setLayout(new BorderLayout());
		add(buttonPanel, BorderLayout.PAGE_START);
		add(logScrollPane, BorderLayout.CENTER);
		this.setDefaultCloseOperation(EXIT_ON_CLOSE);

		// mainContainer.pack();
		addListeners();
	}

	private void addListeners() {
		openButton.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent e) {
				if (conn == null) {
					display.append("Not connected to the DB yet. Please wait ...\n");
				} else {
					if (!labelingUI.isBoundToDataSource()) {
						loadData();
					} else {
						labelingUI.dispose();
						labelingUI = new LabelingUI();
						loadData();
					}
				}
			}
		});

		labelButton.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent e) {

				if (labelingUI.isBoundToDataSource()) {
					labelingUI.initUI();
				} else {
					display.append("The data source for this topic is"
							+ " incomplete. Either the posts, topic "
							+ "descriptions or the annotation examples"
							+ " are missing\n");
				}
			}

		});

		saveButton.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent e) {
				saveToDisk("./posts");
			}
		});

		saveToDB.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent e) {
				saveToDB();
			}
		});
	}

	public void saveToDisk(String directory) {
		for (BlogPost post : labelingUI.getRepo()) {
			display.append(post.writeToDisk(directory));
		}
	}

	/**
	 * Load documents for a specific topic
	 */
	public void loadData() {
		Statement getPostsStatement;
		try {
			String topicNumber = (String) topicNum.getSelectedItem();
			getPostsStatement = conn.createStatement();
			getPostsStatement
					.executeQuery("SELECT * FROM post where topic_no = '"
							+ topicNumber + "'");
			ResultSet returnedPosts = getPostsStatement.getResultSet();
			display.append(lineDividerStars);
			display.append("Loading blog posts for topic " + topicNumber + "\n");
			display.append(lineDividerDashes);

			Vector<BlogPost> repo = new Vector<BlogPost>();
			int count = 0;
			while (returnedPosts.next()) {
				String id = returnedPosts.getString("id");
				Vector<Sentence> sentences = new Vector<Sentence>();

				Statement getSentences = conn.createStatement();
				getSentences
						.executeQuery("select * from sentences where blog_id = '"
								+ id + "'");
				ResultSet returnedSentences = getSentences.getResultSet();
				while (returnedSentences.next()) {
					String content = returnedSentences.getString("content");
					Sentence sentence = new Sentence(content, Sentence.UNKNOWN,
							Sentence.UNKNOWN);
					int sequence = Integer.parseInt(returnedSentences
							.getString("sequence"));
					sentences.add(sequence, sentence);
				}

				Statement getSentenceLabels = conn.createStatement();
				getSentenceLabels
						.executeQuery("select * from labels where blog_id = '"
								+ id + "' and annotator = '"
								+ annotator.getText().trim().toLowerCase()
								+ "'");
				ResultSet returnedSentenceLabels = getSentenceLabels
						.getResultSet();
				if (returnedSentenceLabels.next()) {
					do {
						int topicality = Integer
								.parseInt(returnedSentenceLabels
										.getString("topicality"));
						int sentimentPolarity = Integer
								.parseInt(returnedSentenceLabels
										.getString("sentiment_polarity"));
						int sequence = Integer.parseInt(returnedSentenceLabels
								.getString("sequence"));
						sentences.get(sequence).setTopicality(topicality);
						sentences.get(sequence).setSentimentPolarity(
								sentimentPolarity);
						/*
						 * display.append("Warning: Blog " + id +
						 * " has been annotated by " + annotator.getText() +
						 * " before\n");
						 */
					} while (returnedSentenceLabels.next());
				}
				getSentenceLabels.close();

				BlogPost post = new BlogPost(id, sentences);
				int postTopicalityLabel = Integer.parseInt(returnedPosts
						.getString("topicality"));
				int postSentimentPolarityLabel = Integer.parseInt(returnedPosts
						.getString("sentiment_polarity"));
				post.setSentimentPolarityLabel(postSentimentPolarityLabel);
				post.setTopicality(postTopicalityLabel);
				repo.add(post);
				display.append(count + ": " + id + "\n");
				count++;
			}
			display.append("Success: " + count + " posts loaded\n");

			String topicNo, topicTitle, topicQuery, topicDescription, topicNarrative;
			Statement getTopicStatement = conn.createStatement();
			getTopicStatement
					.executeQuery("select * from topic where topic_no = "
							+ (String) topicNum.getSelectedItem());
			ResultSet rs = getTopicStatement.getResultSet();
			Topic topic = null;
			if (rs.next()) {
				topicNo = rs.getString("topic_no");
				topicTitle = rs.getString("title");
				topicQuery = rs.getString("query");
				topicDescription = rs.getString("description");
				topicNarrative = rs.getString("narrative");
				topic = new Topic(topicNo, topicTitle, topicQuery,
						topicDescription, topicNarrative);
				display.append("Success: Descriptions for topic " + topicNo
						+ " " + "have been loaded\n");
			} else {
				display.append("Error  : No descriptions found for topic "
						+ (String) topicNum.getSelectedItem() + "\n");
			}
			Statement getExamplesStatement = conn.createStatement();
			getExamplesStatement
					.executeQuery("select * from examples where topic_no = "
							+ (String) topicNum.getSelectedItem());
			ResultSet examplesSet = getExamplesStatement.getResultSet();
			Vector<String> examples = new Vector<String>();
			if (examplesSet.next()) {
				examples.add(0, examplesSet.getString("topicality_example1"));
				examples.add(1, examplesSet.getString("topicality_example2"));
				examples.add(2, examplesSet.getString("topicality_example3"));
				examples.add(3, examplesSet.getString("topicality_example4"));
				examples.add(4, examplesSet.getString("sentiment_example1"));
				examples.add(5, examplesSet.getString("sentiment_example2"));
				examples.add(6, examplesSet.getString("sentiment_example3"));
				examples.add(7, examplesSet.getString("sentiment_example4"));
				display.append("Success: Annotation examples for topic "
						+ (String) topicNum.getSelectedItem()
						+ " have been loaded\n");
			} else {
				examples.add(0, "N/A");
				examples.add(1, "N/A");
				examples.add(2, "N/A");
				examples.add(3, "N/A");
				examples.add(4, "N/A");
				examples.add(5, "N/A");
				examples.add(6, "N/A");
				examples.add(7, "N/A");
				display.append("Warning  : No annotation examples found for topic "
						+ (String) topicNum.getSelectedItem() + "\n");
			}
			labelingUI.bindDataSource(repo, topic, examples);
			getExamplesStatement.close();
			returnedPosts.close();
			getPostsStatement.close();
			display.append(lineDividerDashes);
		} catch (SQLException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}
	}

	/**
	 * Save labelled documents to the database
	 */
	public void saveToDB() {
		for (Integer index : labelingUI.getChanged()) {
			BlogPost thisPost = labelingUI.getRepo().get(index);
			System.out.println("Saving " + thisPost.getID());
			display.append(thisPost.writeToDB(conn, annotator.getText()));
		}
	}

	public static void main(String args[]) {
		MainPanel mainPanel = new MainPanel();
		mainPanel.init();

	}
}
